<?php
/*
 * Copyright (c) Taras Kudla, 2010
 */
/*
 * Version 2. improved.
 */
error_reporting(E_ALL);
class GepardException extends Exception {}

class errors
	{
	#
    private $core=null;
    private $ErrorCallBack = null;
    # storing all errors
    private $errorStack = array(null);
    # storing all messages
    private $messagesStack = array(null);
    private $running	= false;
    private $errorStructure = array(
    	# code, which caused an error
    	"SOURCE"=>null,
    	# current system level
    	"LEVEL"=>null,
    	# error type
    	"TYPE"=>null,
    	# file    	
    	"FILE"=>null,
    	# line
    	"LINE"=>null,
    	# error description
    	"DESCRIPTION"=>null
    	);

	function __construct(init & $sysObj){
		$this->core=&$sysObj;	
		set_error_handler(array(&$this,"PHPErrorHandler"),E_ALL);		
		}
	# string aliases if errno
	public function errtype($errno){
	
		switch($errno){
			case _ERR_USER: return "USER"; break;
			case _ERR_NOTICE: return "NOTICE"; break;
			case _ERR_WARNING: return "WARNING"; break;
			case _ERR_FATAL: return "FATAL"; break;
			case _ERR_CRIT: return "CRITICAL"; break;
			default: return "Undefined($errno)";
		}
	}

	public function message($message,$formating=true){
		# messaging improvement
		/*
		 * TODO: Messages in console
		 */
		if( $formatting=true){
		if( $this->core->isconsole()){
			$message ="Message: $message\n\x07";
		} else
		if( $this->core->isloaded("view")){
			$message=$this->core->view->systemplate("message",array("message"=>&$message));
		} else {
			$tmp=$this->core->get("exceptiononerror");
			$this->core->set("exceptiononerror",true);
			try {
				$message = $this->core->view->systemplate("message",array("message"=>&$message));
			} catch ( GepardException $e){
				$message =$e->getMessage();
			}
		}
		}
		$this->messagesStack[]=$message;
		return $message;
	}
	# alarm's
	public function alarm(){
		
	}
	# native php handler
	public function PHPErrorHandler($errno, $errstr, $errfile, $errline){
		
        	$errfile=preg_replace("/^(.+)[\/\\\](.+)(\.php)$/","$2",$errfile);
        	$errstr=strip_tags($errstr);
		$errstr=str_replace($this->core->path(),"",$errstr);
        	switch ($errno)
        		{
           		case E_ERROR:
            		case E_USER_ERROR:
			$type=_ERR_USER;           	
            		break;
            		case E_WARNING:
            		case E_USER_WARNING:
               		$type=_ERR_WARNING;
             		break;
            		case E_NOTICE:
            		case E_USER_NOTICE:
              		$type=_ERR_NOTICE;            	
            		break;	
            		default:
            		$type=$errno;
            		break;
        	}
        return $this->create("PHP NATIVE",$errstr,$type,$errfile,$errline);
        }		
	/*
	 * Main error processing function
	 */   
	public function create($source="NATIVE",$description=null,$type=_ERR_USER,$file=null,$line=null){
		# adding to global errors stack
		$error = $this->errorStructure;
		$level = ( $this->core->getenvlayer()==_ENV_MOD?"MODULE":"KERNEL");
		$error["SOURCE"]	= $source;
		$error["TYPE"]		= $type;
		$error["FILE"]		= $file;
		$error["LINE"]		= $line;
		$error["DESCRIPTION"]   = $description;
		$error["LEVEL"]		= $level;
		
		$this->errorStack[]=$error;

		if( $this->running ){
			//return true;
		}
		$this->running=true;
		# Prepare for writing to log
		$typename = $this->errtype($type);
		$envlayer= $this->core->getenvlayer();
		$env = $this->core->getenvcaller();
		$sourcename = $source."(".( $envlayer==_ENV_MOD?$env["MOD"]."-".$env["NAME"]:"KERNEL").")";
		$folder = $this->core->path();	
		$logdescription=(!is_null($file)?"($file:$line)":null).$description;
		switch($type){
			case _ERR_USER: $log = _LOG_MESSAGE; break;
			case _ERR_NOTICE: $log = _LOG_NOTICE; break;
			case _ERR_WARNING:
			case _ERR_FATAL: $log = _LOG_ERROR; break;
			case _ERR_CRIT: $log = _LOG_CRITICAL; break;
			default: $log = _LOG_ERROR;
		}
		/*
		 * Writing to log
		 */
		if( $this->core->isloaded("log") && strtolower($source)!="log")
			$this->core->log->write($logdescription,$log,_ERROR_LOG,$sourcename);
		else {
			# trying to load log object
			$this->core->setstate("exceptiononerror",true);
			try {
				# FIXME:
				//$this->core->log->write($logdescription,$log,_ERROR_LOG,$sourcename);
			} catch (GepardException $e){
			
			}
			$this->core->restorestate("exceptiononerror");
		}		
		/*
		 *  Printing on screen
		 */
		if( $this->core->get("exceptiononerror") ){
			throw new GepardException($logdescription);
			return true;
		}		 
		 
		if( !$this->core->get("messageonerror") && strcmp($source,"PHP NATIVE")!=0){
			return true;
		}
		/*
		 * Checking if console mode
		 */
		else if( $this->core->get("runmode")==_CONSOLE_RUNMODE){
			$description=preg_replace("/(\<br\>)|(\<hr\>)|(\")/iUs","\\n",$description);
    		$description=preg_replace("/(\<b\>)|(\<\/b\>)/iUs","",$description);  		
			print "\n\n-----\t\tError corrupted\t\t-----\n\n";
			print "SOURCE:       \t$source\n";
			print "TYPE:         \t$type\n";
			print "LEVEL:        \t$level\n";
			print "FILE:         \t$file\n";
			print "LINE:         \t$line\n";
			print "DESCRIPTION:  \t$description\n\n";
			print "-----\t\tGepard Error Report\t\t-----\n\n";
		}
		/*
		 * Checking if it's module and _STANDARD SECURE MODE
		 */
		else if( $envlayer==_ENV_MOD && $this->core->isloaded("view") && $this->core->get("secure")==_STANDARD && $type!=_ERR_FATAL && $type!=_ERR_CRIT  ){
			
			$text = "Error here";
			$count = $env["ERROR_COUNT"]++;
			$errordata = $env["ERROR"];			
			$this->core->updateenvcaller("error_count",$count);
			$this->core->updateenvcaller("error",$errordata);

			$this->running=false;
			return true;
		}
		
		/*
		 * Checking if template is available
		 */
		else if ( file_exists($folder."view/errors/error.html") ){
			$text = file_get_contents($folder."view/errors/error.html");
			$text=preg_replace(array(
				"/\{\s*#source\s*\}/is",
				"/\{\s*#type\s*\}/is",
				"/\{\s*#file\s*\}/is",
				"/\{\s*#level\s*\}/is",
				"/\{\s*#line\s*\}/is",
				"/\{\s*#description\s*\}/is",
				"/\{\s*#debug\s*\}/is",
				"/\{\s*#callerdump\s*\}/is",
				"/\{\s*#errorstackdump\s*\}/is",
			),array(
				$sourcename,
				$typename,
				$file,
				$level,
				$line,
				$description,
				nl2br($this->core->GetDebug(_STRING)),
				null,
				null			
			),$text);
			print $text;
		}		
		/*
		 * Printing error
		 */
		else {
			/*
			 * Default html code
			 */
			print "<h3>Error</h3>";
			print "<hr>";
			print "<br>SOURCE:       \t$source<br><br>";
			print "TYPE:         \t$typename<br><br>";
			print "LEVEL:		 \t$level<br><br>";
			print "FILE:         \t$file<br><br>";
			print "LINE:         \t$line<br><br>";
			print "DESCRIPTION:  \t$description<br><br><hr>";
			print "-----\t\tGepard Error Report\t\t-----<br><br>";			
		}		
		/*
		 * Just exiting, without connection closes, etc.
		 */
		$this->running=false;
		exit;
	}        
	# Getting last error
	public function last(){
		return $this->errorStack[count($this->errorStack)-1];		
	}
	# getting last message
	public function lastmessage(){
		return $this->messagesStack[count($this->messagesStack)-1];
	}
}
?>